const Service = require('egg').Service;
const lodash = require('lodash');
const jwt = require('jsonwebtoken');
class AuthService extends Service {

    /**
     * @param {提交的数据} data 
     * @return token || -1
     */
    async verifyLogin(user) {
        const { ctx, app } = this;
        //通过用户名/手机号获取用户信息
        let users = await ctx.service.users.findBySole(user.login_name);
        if (users.length <= 0) {
            await app.utils.error.throw("用户不存在 ！！！", 311);
        }
        let userData = users[0];
        let psd = await ctx.service.md5.saltPasswordFunc(user.password, userData.salt);
        //匹配密码对
        if (userData.password != psd) {
            await app.utils.error.throw("密码错误 ！！！", 312);
        }
        return {
            code: 200,
            msg: "成功",
            user: userData
        }
    }


    /**
     * @param userid,longtime 
     * @return 1，0
     */
    async genToken(userid, longtime) {
        const uuid = require('node-uuid');
        const { ctx, app } = this;
        let token = await ctx.service.md5.cryptoPassFunc(uuid.v1() + new Date().getTime());
        await app.redis.set(token, userid, 'PX', longtime);
        return token;
    }

    /**
     * @param 生成图形验证码
     * @return boolean
     */
    async getImgCode() {
        const svgCaptcha = require('svg-captcha');
        const uuid = require('node-uuid');
        const { ctx, app, config } = this;
        var captcha = svgCaptcha.create({
            // 翻转颜色 
            inverse: false,
            // 字体大小 
            fontSize: 36,
            // 噪声线条数 
            noise: 3,
            // 宽度 
            width: 80,
            // 高度 
            height: 40,
        });
        let code = captcha.text.toLowerCase();
        let imgSvg = String(captcha.data);
        let imgbase64 = "data:image/svg+xml;base64," + Buffer.from(imgSvg).toString('base64');//转换为base64
        let key = await ctx.service.md5.cryptoPassFunc(uuid.v1() + new Date().getTime());
        await ctx.service.redis.set(key, code, config.auth.imgCodeTime);
        return {
            "code": imgbase64,
            "key": key
        };
    }

    /**
     * @param 验证验证码
     * @return boolean
     */
    async valiCode(code, key) {
        const { ctx, app } = this;
        let recode = await ctx.service.redis.get(key);
        recode = recode || "";
        code = code || "";
        console.log("验证图形验证码", { recode, code })
        if (recode.toLowerCase() != code.toLowerCase()) {
            await app.utils.error.throw("图形验证码错误");
        }
    }

    /**
     * 验证请求路径是否存在与白名单
     * @param {*} path 
     */
    async aoneReq(path) {
        const { config } = this;
        let aone = false;
        let anonList = config.auth.anonList;
        for (var i = 0; i < anonList.length; i++) {
            if (path.indexOf(anonList[i]) > -1) {
                aone = true;
                break;
            }
        }
        return aone;
    }

    /**
     * 验证token
     */
    async getColonyUserId(token) {
        const { ctx, app } = this;
        //优先取传入的token
        token = token || await ctx.request.headers.authorization;
        let userid = await ctx.service.redis.get(token);
        console.log("userid========", userid);
        if (await app.utils.validator.isEmpty(userid)) {
            await app.utils.error.throw("token令牌无效 ！！！", -99, 401);
        }
        return userid;
    };

    /**
     * 退出登录
     */
    async loginOut() {
        const { ctx } = this;
        const token = await ctx.request.headers.authorization;
        //删除key
        await ctx.service.redis.del(token);
    }

    /**
     * 生成token
     * @param {*} password 
     */
    async genJwtoken(content) {
        const { ctx, config } = this;
        console.log("content", content);
        let pem = await ctx.service.rsa.getNodeRSA();
        let token = await jwt.sign(content, pem.privatePem, { expiresIn: config.auth.sysTokenTime });
        return token;
    }

    /**
     * 验证token
     */
    async verifyToken(token) {
        const { ctx, app } = this;
        let pem = await ctx.service.rsa.getNodeRSA();
        try {
            let result = await jwt.verify(token, pem.privatePem);
            console.log("token-解析结果==", result);
            let { exp = 0 } = result, current = Math.floor(Date.now() / 1000);
            let userid = await ctx.service.redis.get(token);
            if (current <= exp && userid) {
                //如果发现用户权限过期，重新拉取一次权限
                console.log(token + "====>验证通过");
                return result;
            } else {
                console.log(token + "====>验证失败");
                //抛出异常
                await app.utils.error.throw("token令牌无效 ！！！", -99, 401);
                return false;
            }
        } catch (error) {
            //抛出异常
            await app.utils.error.throw("token令牌无效 ！！！", -99, 401);
            return false;
        }
    };

    /**
     * 验证功能数据权限
     */
    async verifyFunction(token, path) {
        const { ctx, app } = this;
        let funclist = await ctx.service.auth.queryFunticonByToken(token);
        // console.log("数据权限列表", funclist);
        let isAuth = false;
        for (var i = 0; i < funclist.length; i++) {
            let function_key = funclist[i].function_key || "";
            if (function_key == "") {
                function_key = [];
            } else {
                function_key = function_key.split(",");
            }
            // console.log("验证单个数据权限", function_key);
            for (var j = 0; j < function_key.length; j++) {
                let fncItem = (function_key[j] || "").replace(/\#/g, "\/");
                // console.log("验证path", { fncItem, path });
                if (fncItem == path) {
                    console.log("数据权限通过===",path);
                    isAuth = true;
                    break;
                }
            }
        }

        if (!isAuth) {
            await app.utils.error.throw("访问权限不足", 403);
        }
    };

    /**
     * 通过角色查询权限列表
     */
    async queryMenuByToken(token, isNone) {
        const { ctx, app } = this;
        if (isNone != true) {
            let result = await ctx.service.auth.verifyToken(token);
        }
        let authdata = {};
        if (token) {
            let setKey = token + "_role_menu";
            authdata = await ctx.service.redis.get(setKey);
            if (authdata) {
                return JSON.parse(authdata);
            } else {
                let authList = await ctx.service.sysMenu.queryTreeList();
                let authTreeList = await app.utils.tool.toTreeList(authList, "menu_id", "parent_id", [["title", "menu_name"], ["value", "menu_id"], ["key", "menu_id"]]);
                authdata = { authList, authTreeList };
                await ctx.service.redis.set(setKey, JSON.stringify(authdata), 60 * 10);
                return authdata;
            }
        }
        //返回空的权限列表
        return [];

    }

    /**
     * 通过角色查询功能数据权限列表
     */
    async queryFunticonByToken(token, isNone) {
        const { ctx, app } = this;
        if (isNone != true) {
            let result = await ctx.service.auth.verifyToken(token);
        }
        let functionlist = [];
        if (token) {
            let setKey = token + "_role_funciton";
            // functionlist = await ctx.service.redis.get(setKey);
            functionlist = null;
            if (functionlist) {
                return JSON.parse(functionlist);
            } else {
                //根据userid，查询角色id
                let user_id = await ctx.service.redis.get(token);
                let querysql = `SELECT f.* FROM sys_role_function rf 
                left join sys_function f on f.function_id=rf.function_id 
                where f.deleted='0' and rf.role_id in(
                    SELECT t.role_id FROM sys_user_role t 
                    where t.user_id=:user_id )`;
                let functionlist = await ctx.model.query(querysql,
                    { replacements: { user_id }, raw: true, type: app.Sequelize.QueryTypes.SELECT });

                await ctx.service.redis.set(setKey, JSON.stringify(functionlist), 60 * 10);
                return functionlist;
            }
        }
        //返回空的权限列表
        return [];

    }


}

module.exports = AuthService;
